#define SumIsDoneWithException
using System;
using System.Threading;

public static class Program {
   public static void Main() {
      // Initialize a delegate variable to refer 
      // to the method we want to call asynchronously
      SumDelegate sumDelegate = Sum;

#if !SumIsDoneWithException
      sumDelegate.BeginInvoke(1000000000, SumIsDone, sumDelegate);
#else
      sumDelegate.BeginInvoke(10000000000, SumIsDone, sumDelegate);
#endif

      // Executing some other code here would be useful...

      // For this demo, I'll just suspend the primary thread
      Console.ReadLine();
   }

#if !SumIsDoneWithException
   private static void SumIsDone(IAsyncResult ar) {
      // Extract the SumDelegate (state) out of the IAsyncResult object
      SumDelegate sumDelegate = (SumDelegate) ar.AsyncState;

      // Get the result
      UInt64 sum = sumDelegate.EndInvoke(ar);

      // Show the result
      Console.WriteLine("Sum={0}", sum);
   }
#else
   private static void SumIsDone(IAsyncResult ar) {
      // Extract the SumDelegate (state) out of the IAsyncResult object
      SumDelegate sumDelegate = (SumDelegate)ar.AsyncState;

      try {
         // Get the result; this could throw an OverflowException
         UInt64 sum = sumDelegate.EndInvoke(ar);

         // Show the result
         Console.WriteLine("Sum={0}", sum);
      }
      catch (OverflowException) {
         // EndInvoke threw an OverflowException; recover gracefully
         Console.WriteLine("Sum can't be shown: number is too big.");
      }
   }
#endif

   private delegate UInt64 SumDelegate(UInt64 n);

   private static UInt64 Sum(UInt64 n) {
      UInt64 sum = 0;
      for (UInt64 i = 0; i <= n; i++) {
         checked {   
            // I use checked code so that an OverflowException gets 
            // thrown if the sum won't fit in a UInt64.
            sum += i;
         }
      }
      return sum;
   }
}
